package com.archerdu.base.dao;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Example;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.archerdu.commons.util.BeanUtils;

/**
 * DAO层的hibernate实现基类，定义通用方法
 * 
 * @projectName springDemo
 * @description DAO层的hibernate实现基类，定义通用方法
 * @author archer du
 * @createDate 2013年9月27日 下午5:27:07
 * @updateUser dxf
 * @updateDate 2013年9月27日 下午5:27:07
 * @updateRemark 新建
 * @version 0.0.1
 */
public class HibernateBaseDao<E extends BaseEntity<K>, K extends Serializable> extends HibernateDaoSupport implements
        IBaseDao<E, K> {

    private static final long  serialVersionUID = 6019720414553232833L;
    protected static final Log LOG              = LogFactory.getLog(HibernateBaseDao.class);

    protected Class<E>         entityClass;

    /**
     * 构造方法，初始化实体类
     */
    @SuppressWarnings("unchecked")
    public HibernateBaseDao() {
        // 初始化实体类
        this.entityClass = (Class<E>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
    }

    /**
     * 取得dao实现类的类
     */
    public Class<E> getEntityClass() {
        return entityClass;
    }

    /**
     * 保存对象
     */
    public void save(E entity) {
        getHibernateTemplate().save(entity);
    }

    /**
     * 保存实现了TreeNode接口的对象
     * @see TreeNode
     */
    @SuppressWarnings("unchecked")
    @Override
    public void save(TreeNode<E, K> entity) {
        TreeNodeUtil.preEdit(entity, (TreeNode<E, K>) this.get(entity.getId()));
        getHibernateTemplate().save(entity);
    }

    /**
     * 实现了TreeNode接口的merge
     */
    @SuppressWarnings("unchecked")
    @Override
    public void merge(TreeNode<E, K> entity) {
       TreeNodeUtil.preEdit(entity, (TreeNode<E, K>) this.get(entity.getId()));
       E e = get(entity.getId());
        // 复制默认属性
        BeanUtils.copyProperties(entity, e);
        getHibernateTemplate().merge(e);
    }
    
    /**
     * merge
     */
    @Override
    public void merge(E entity) {
        E e = get(entity.getId());
        // 复制默认属性
        BeanUtils.copyProperties(entity, e);
        getHibernateTemplate().merge(e);
    }

    /**
     * 更新对象
     */
    public void update(E entity) {
        E e = get(entity.getId());
        // 复制默认属性
        BeanUtils.copyProperties(entity, e);
        getHibernateTemplate().update(e);
    }

    /**
     * 删除对象
     */
    public void delete(E entity) {
        deleteByKey(entity.getId());
    }

    /**
     * 通过键值删除对象
     */
    public void deleteByKey(K key) {
        getHibernateTemplate().delete(get(key));
    }

    /**
     * 由parentid获取对象集合
     */
    @SuppressWarnings("unchecked")
    public List<E> findByParentId(K key) {
        DetachedCriteria criteria = getCriteria();
        criteria.add(Restrictions.eq(PARENT_ID, key));
        return getHibernateTemplate().findByCriteria(criteria);
    }

    /**
     * 根据键值获取对象
     */
    public E get(K key) {
        return (E) (getHibernateTemplate().get(getEntityClass(), key));
    }

    /**
     * 获取全部对象
     */
    public List<E> findAll() {
        return getHibernateTemplate().loadAll(getEntityClass());
    }

    /**
     * 获取对象集合
     */
    public List<E> findAll(E entity) {

        DetachedCriteria criteria = getCriteria();
        criteria.add(Example.create(entity));

        return findAll(criteria);
    }

    /**
     * 获取对象集合
     */
    public List<E> findAll(E entity, Order order) {

        DetachedCriteria criteria = getCriteria();
        criteria.add(Example.create(entity));
        criteria.addOrder(order);
        return findAll(criteria);
    }

    @Override
    public List<E> findAll(E entity, List<Order> orderList) {
        DetachedCriteria criteria = getCriteria();
        criteria.add(Example.create(entity));
        for (Order order : orderList) {
            criteria.addOrder(order);
        }
        return findAll(criteria);
    }

    @SuppressWarnings("unchecked")
    @Override
    public List<E> findAll(DetachedCriteria criteria) {

        return getHibernateTemplate().findByCriteria(criteria);
    }

    @SuppressWarnings("unchecked")
    public E findUnique(DetachedCriteria criteria) {
        List<E> list = getHibernateTemplate().findByCriteria(criteria, 0, 1);
        if (list.size() > 0) {
            return list.get(0);
        } else {
            return null;
        }
    }

    /**
     * 通过criteria查询对象集合
     */
    @SuppressWarnings("unchecked")
    public List<E> findByCretira(DetachedCriteria criteria) {
        return getHibernateTemplate().findByCriteria(criteria);
    }

    /**
     * 创建托管状态criteria对象
     */
    @Override
    public DetachedCriteria getCriteria() {
        return DetachedCriteria.forClass(getEntityClass());
    }

    /**
     * 分页查询对象集合
     */
    @Override
    public IPage<E> pageSearch(int pageNo, int pageSize) {
        return pageSearch(getCriteria(), pageNo, pageSize);
    }

    /**
     * 通过criteria分页查询对象集合
     */
    @SuppressWarnings("unchecked")
    @Override
    public IPage<E> pageSearch(DetachedCriteria criteria, int pageNo, int pageSize) {

        IPage<E> page = new Page<E>(pageNo, pageSize);

        page.setList((List<E>) getHibernateTemplate()
                .findByCriteria(criteria, page.getFitstIndex(), page.getMaxIndex()));
        // 查询记录总数
        criteria.setProjection(Projections.rowCount());
        List<Integer> list = getHibernateTemplate().findByCriteria(criteria, 0, 1);
        if (list != null && list.size() > 0)
            page.setTotal(list.get(0).longValue());
        LOG.info("page search result's amount is " + page.getTotal());
        return page;
    }

    /**
     * 通过对象分页查找对象集合
     */
    @Override
    public IPage<E> pageSearch(E entity, int pageNo, int pageSize) {

        DetachedCriteria criteria = getCriteria();
        criteria.add(Example.create(entity));

        return pageSearch(criteria, pageNo, pageSize);
    }
}
